import datetime
import json
import logging
import os

from django.utils import timezone

from ninja import Router, Query
from PIL import Image
from io import BytesIO

from apps.commom.user import UserSerializer, WxAppletsLoginSchema, RegionInfoSerializer
from apps.commom.water_droplets import WaterDropletsRecordSerializer
from apps.user_applets.user.schema import UserAddWaterDropNumberSchema, UpdateUserNickNameSchema, GetQrCodeSchema, \
    GetShareLinkSchema, WaterDropletsRecordFilter
from models.choices import WaterCardType
from models.models import User, WaterDropletsRecord, SignRecord, WaterDropletsTask, RegionInfo
from django.core.cache import cache

from apps.schemas import R
from utils.auth import AppletAuthBearer
from utils.decorators import handle_exception
from utils.encryption import make_token
from utils.snowflake import generate_random_code
from utils.time import get_month_days
import requests

from utils.wx import get_access_token
from water_applets import settings

info_logger = logging.getLogger(settings.RUNNING_LOG_NAME)

applet_user_router = Router(tags=['前端用户'])


@applet_user_router.post("/user/login", summary="微信登录")
@handle_exception("登录失败")
def wx_login(request, data: WxAppletsLoginSchema):
    """
    微信小程序登录
    """
    if not data.code:
        return R.fail(msg="code is required")
    url = settings.WX_LOGIN_URL.format(code=data.code)
    res = requests.get(url)
    if res.status_code != 200:
        return R.fail(msg="code is required")
    res_dict = json.loads(res.content)
    # todo 测试用
    # res_dict = {
    #     "openid": "oD5ip671iVoaI2Umrd48Yk1sJ99s"
    # }
    # phone_number = "18328432590"
    # todo 测试用
    token = get_access_token(settings.WX_GET_TOKEN_URL)
    url = settings.WX_GET_PHONE_NUMBER_URL.format(access_token=token)
    headers = {"Content-Type": "application/json"}
    para = {'code': data.phoneCode}
    response = requests.post(url, json=para, headers=headers)
    res = response.json()
    phone_number = ""

    if res['errcode'] == 0:  # 成功获取phonenumber
        phone_number = res['phone_info']['phoneNumber']
    else:
        R.ok(msg="获取手机号失败")
    user, new = User.objects.get_or_create(openid=res_dict['openid'])
    if new:
        # 避免用户邀请码重复
        invite_codes = User.objects.all().values_list('invite_code', flat=True)
        while True:
            invite_code = generate_random_code(10)
            if invite_code not in invite_codes:
                break
        user.invite_code = invite_code
        user.phone_number = phone_number
        if data.invite_code:
            # 邀请码不为空，更新用户邀请人id
            invite_user = User.objects.get(invite_code=data.invite_code)
            user.invite_id = invite_user.id
            # 存储邀请人记录
            # InvitationRecord.objects.create(invitee=user, inviter=invite_user, time=timezone.now())
        user.save()
    else:
        user.phone_number = phone_number if user.phone_number != phone_number else user.phone_number
        user.save()
    request.user = user
    token = make_token()
    login_user_key = settings.REDIS_APPLETS_LOGIN_TOKEN_KEY.format(user_id=user.id)
    cache.set(login_user_key, token, settings.APPLETS_LOGIN_TOKEN_EXPIRE)
    task = WaterDropletsTask.objects.get(id=1)
    # todo 每次登录增加水滴记录
    if task.on:
        WaterDropletsRecord.objects.create(user_id=user.id, op_type=WaterCardType.GET,
                                           droplet_number=task.droplet_number, op_time=timezone.now())
        # todo 增加用户的水滴水量
        user.water_droplets_number += task.droplet_number
        user.save()
    return R.ok(data={"user": UserSerializer(user).data, "token": token})


@applet_user_router.get("/user/info/{user_id}", summary="获取用户信息", auth=AppletAuthBearer())
@handle_exception("获取用户信息失败")
def get_user(request, user_id: int):
    """
    获取用户信息
    """
    user = User.objects.get(id=user_id)
    return R.ok(data=UserSerializer(user).data)


@applet_user_router.post("/user/get_share_qrcode", summary="获取推广二维码", auth=AppletAuthBearer())
@handle_exception("获取推广二维码失败")
def get_qrcode(request, data: Query[GetQrCodeSchema]):
    """
    获取推广二维码
    """
    req_data = {"page": data.page, "scene": f"invite_code={request.user.invite_code}",
                "check_path": True,
                "env_version": "release"}
    response = requests.post(
        url=f"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={get_access_token()}",
        verify=False,
        data=json.dumps(req_data))
    img = Image.open(BytesIO(response.content))
    folder = f"static/images/qrcode/{request.user.id}"
    filename = data.page.replace("/", "_")
    save_path = f"{folder}/{filename}.png"
    if not os.path.exists(folder):
        os.makedirs(folder)
    img.save(save_path)
    return R.ok(data={"qrcode": save_path})


@applet_user_router.post("/user/get_share_url", summary="获取分享链接", auth=AppletAuthBearer())
@handle_exception("获取分享链接失败")
def get_share_url(request, data: Query[GetShareLinkSchema]):
    """
    获取分享链接
    """
    req_data = {
        "page_url": f"{data.page}?invite_code={request.user.invite_code}",
        "page_title": data.title,
        "is_permanent": False
    }
    response = requests.post(
        url=f"https://api.weixin.qq.com/wxa/genwxashortlink?access_token={get_access_token()}",
        verify=False,
        data=json.dumps(req_data))
    return R.ok(data={"url": json.loads(response.content.decode())})


@applet_user_router.post("/user/set_user_info", summary="设置用户头像和昵称", auth=AppletAuthBearer())
@handle_exception("设置用户头像和昵称失败")
def set_nickname(request, data: UpdateUserNickNameSchema):
    user = request.user
    user.nickname = data.nickname
    user.avatar = data.avatar
    user.save()
    return R.ok(msg="设置成功")


# 位图记录签到状态，1为已签到，0为未签到，key为sign_user_id_年月
@applet_user_router.get("/user/sign", summary="用户签到", auth=AppletAuthBearer())
@handle_exception("签到失败")
def sign_in(request):
    now = datetime.datetime.now()
    key = now.strftime("%Y/%m")
    sign_objs = SignRecord.objects.filter(user=request.user, key=key)
    if sign_objs.exists():
        sign_obj = sign_objs.first()
        sign_obj.sign_content = f"{sign_obj.sign_content[:now.day - 1]}1{sign_obj.sign_content[now.day:]}"
        sign_obj.save()
        return R.ok(msg="签到成功")
    days = get_month_days(now.year, now.month)
    sign_content = "0" * days
    sign_content = f"{sign_content[:now.day - 1]}1{sign_content[now.day:]}"
    SignRecord.objects.create(user=request.user, key=key, sign_content=sign_content)
    return R.ok(msg="签到成功")


@applet_user_router.get("/user/sign_record", summary="获取用户签到记录", auth=AppletAuthBearer())
@handle_exception("获取用户签到记录失败")
def get_sign_record(request):
    user = request.user
    now = datetime.datetime.now()
    key = now.strftime("%Y/%m")
    record = SignRecord.objects.filter(user=user, key=key)
    if record.exists():
        record = record.first()
        return R.ok(data=record.sign_content)
    else:
        now = datetime.datetime.now()
        days = get_month_days(now.year, now.month)
        sign_content = "0" * days
        record, new = SignRecord.objects.get_or_create(user=request.user, key=key, sign_content=sign_content)
        return R.ok(data=record.sign_content)


@applet_user_router.post("/user/add_water_drop", summary="用户增加水滴", auth=AppletAuthBearer())
@handle_exception("增加水滴失败")
def add_water(request, data: Query[UserAddWaterDropNumberSchema]):
    user = request.user
    user.water_droplets_number += data.water_drop_number
    user.save()
    WaterDropletsRecord.objects.create(user_id=user.id, op_type=WaterCardType.GET,
                                       droplet_number=data.water_drop_number, op_time=timezone.now())
    return R.ok(msg="增加成功")


@applet_user_router.get("/region_infos", summary="获取区域信息", auth=AppletAuthBearer())
@handle_exception("获取区域信息失败")
def get_region_infos(request):
    """
    获取区域信息
    """
    region_infos = RegionInfo.objects.filter(parent_id=0)
    return R.ok(data=RegionInfoSerializer(region_infos, many=True).data)


@applet_user_router.get("/region_info/{pid}", summary="查询下属区域信息", auth=AppletAuthBearer())
@handle_exception("查询下属区域信息")
def get_region_infos(request, pid: int):
    """
    获取区域信息
    """
    region_infos = RegionInfo.objects.filter(parent_id=pid)
    return R.ok(data=RegionInfoSerializer(region_infos, many=True).data)


@applet_user_router.get("/user/get_water_drop_info", summary="获取用户水滴信息", auth=AppletAuthBearer())
@handle_exception("获取用户水滴信息失败")
def get_water_drop_info(request, filters: WaterDropletsRecordFilter = Query(...)):
    """
    获取用户水滴信息
    """
    user = request.user
    today = datetime.datetime.now()
    current_month = datetime.datetime(today.year, today.month, 1, 0, 0, 0)
    records = WaterDropletsRecord.objects.filter(user_id=user.id, op_time__gt=current_month)
    if filters.op_type is not None and filters.op_type not in [1, 2]:
        return R.ok(msg="类型错误")
    records = filters.filter(records)
    get_total = 0
    consume_total = 0
    for item in records:
        if item.op_type == WaterCardType.GET:
            get_total += item.droplet_number
        else:
            consume_total += item.droplet_number
    result = {
        "get_total": get_total,
        "consume_total": consume_total,
        "water_droplets": user.water_droplets_number,
        "items": WaterDropletsRecordSerializer(records, many=True).data
    }
    return R.ok(result)
